package service

import (
	"context"
	"github.com/ammyhaber/seckill/service/inventory/model"
	"log"
	"sync"
	"time"
)

// InventorySyncService 库存同步服务
type InventorySyncService struct {
	inventoryService *InventoryService
	syncInterval     time.Duration
	syncLock         sync.Mutex
	ctx              context.Context
	cancel           context.CancelFunc
}

// NewInventorySyncService 创建库存同步服务
func NewInventorySyncService(inventoryService *InventoryService, syncInterval time.Duration) *InventorySyncService {
	ctx, cancel := context.WithCancel(context.Background())
	return &InventorySyncService{
		inventoryService: inventoryService,
		syncInterval:     syncInterval,
		ctx:              ctx,
		cancel:           cancel,
	}
}

// Start 启动同步服务
func (s *InventorySyncService) Start() {
	log.Println("库存同步服务启动，同步间隔:", s.syncInterval)
	
	// 启动定时同步任务
	go s.scheduledSync()
	
	// 启动全量同步任务
	go s.fullSync()
}

// Stop 停止同步服务
func (s *InventorySyncService) Stop() {
	s.cancel()
	log.Println("库存同步服务已停止")
}

// scheduledSync 定时同步任务
func (s *InventorySyncService) scheduledSync() {
	ticker := time.NewTicker(s.syncInterval)
	defer ticker.Stop()
	
	for {
		select {
		case <-ticker.C:
			s.syncAllInventory()
		case <-s.ctx.Done():
			return
		}
	}
}

// fullSync 全量同步任务（每天凌晨执行）
func (s *InventorySyncService) fullSync() {
	for {
		// 计算下一个凌晨3点的时间
		now := time.Now()
		next := time.Date(now.Year(), now.Month(), now.Day(), 3, 0, 0, 0, now.Location())
		if now.After(next) {
			next = next.Add(24 * time.Hour)
		}
		
		// 等待到达指定时间
		timer := time.NewTimer(next.Sub(now))
		select {
		case <-timer.C:
			// 执行全量同步
			log.Println("开始执行库存全量同步...")
			s.fullSyncInventory()
			log.Println("库存全量同步完成")
		case <-s.ctx.Done():
			timer.Stop()
			return
		}
	}
}

// syncAllInventory 同步所有商品库存
func (s *InventorySyncService) syncAllInventory() {
	// 获取锁防止并发同步
	s.syncLock.Lock()
	defer s.syncLock.Unlock()
	
	// 获取所有商品ID
	details, err := s.inventoryService.inventoryDAO.GetInventoryDetailList()
	if err != nil {
		log.Printf("获取库存列表失败: %v\n", err)
		return
	}
	
	// 逐个同步
	for _, detail := range details {
		err := s.inventoryService.syncInventoryToDB(s.ctx, detail.ProductID)
		if err != nil {
			log.Printf("同步商品[%d]库存失败: %v\n", detail.ProductID, err)
		}
	}
	
	log.Println("定时库存同步完成")
}

// fullSyncInventory 全量同步库存（从数据库到Redis）
func (s *InventorySyncService) fullSyncInventory() {
	// 获取锁防止并发同步
	s.syncLock.Lock()
	defer s.syncLock.Unlock()
	
	// 从数据库获取所有库存信息
	details, err := s.inventoryService.inventoryDAO.GetInventoryDetailList()
	if err != nil {
		log.Printf("获取库存列表失败: %v\n", err)
		return
	}
	
	// 转换为库存模型
	inventories := make([]*model.Inventory, 0, len(details))
	for _, detail := range details {
		inventories = append(inventories, &detail.Inventory)
	}
	
	// 重新预热到Redis
	err = s.inventoryService.redisCache.WarmUpInventory(s.ctx, inventories)
	if err != nil {
		log.Printf("库存全量同步到Redis失败: %v\n", err)
		return
	}
	
	log.Println("库存全量同步到Redis完成")
}

// SyncInventory 手动触发指定商品的库存同步
func (s *InventorySyncService) SyncInventory(productID int64) error {
	return s.inventoryService.syncInventoryToDB(s.ctx, productID)
}